#include <assert.h>
#include <stdlib.h>
#include <string.h>
#include "genir.h"
#include "error.h"
#include "inter_code.h"
#include "symbol.h"
#include "sym_table.h"
#include "semantic.h"
#include "gp_list.h"
#include "common.h"


label_stack_t lb_stack_g;
void label_stack_init(void)
{
	INIT_LIST_HEAD(&lb_stack_g.begin);
	INIT_LIST_HEAD(&lb_stack_g.end);
}

void label_stack_destroy(void)
{
	gp_list_free(&lb_stack_g.begin);
	gp_list_free(&lb_stack_g.end);
}

/*
	入栈一对标签
	// 注意，参数可以是 NULL
*/
void push_labels(inter_inst_t *lb_begin, inter_inst_t *lb_end)
{
	gp_node_add_tail(lb_begin, &lb_stack_g.begin);
	gp_node_add_tail(lb_end, &lb_stack_g.end);
}


/*
	出栈一对标签
*/
void pop_labels(void)
{
	gp_node_delete_tail(&lb_stack_g.begin);
	gp_node_delete_tail(&lb_stack_g.end);
}

/*
	获取栈顶标签
*/
inter_inst_t *get_top_label(struct list_head *head)
{
	if(list_empty(head))
		return NULL;
	gp_node_t *label = container_of(head->prev, gp_node_t, entry);
	return label->addr;
}


var_t *get_step(var_t *v) 
{
    assert(v);
    if(IS_BASE(v))
        return sym_tab_g.one;
	else if(TYPE_IS_CHAR(v)) 
		return sym_tab_g.one;
	else if(TYPE_IS_INT(v))
		return sym_tab_g.four;
	else 
        assert(0);
}


void add_inst(inter_inst_t *inst)
{
    assert(inst);
	// 分析函数的时候，才生成指令。全局作用域不需要指令
	if(sym_tab_g.cur_fun) { 
		list_add_tail(&inst->entry, &sym_tab_g.cur_fun->inter_code);
		
		if(inst->op == IR_OP_DECL) // 统计局部变量的个数（不包括参数）
			sym_tab_g.cur_fun->local_vars_cnt++;
	} else {
		free(inst);
	}	
}

// 增加中间变量的可读性
void gen_fun_called_note(var_t *des, fun_t *fun, struct list_head *head)
{
    assert(des && fun);
    int len = 0;
    if(head) {  // 计算长度
        gp_node_t *pos;
        var_t *para;
    	list_for_each_entry(pos, head, entry) { 
            para = pos->addr;
		    len += strlen(para->note);
	    }
        // 3 = "(" 和 ")" 和  "\0"       “,” + “空格”
        len += strlen(fun->note) + (fun->para_len - 1) * 2 + 3;
    } else {
        len += strlen(fun->note)  + 3;

    }

    free(des->note);     
    des->note = calloc(1, len);
    if(!des->note) {
        SYSTEM_FATAL_ERR(MEM_ALLOC_FAILED);
    }
    strcat(des->note, fun->note); // 字符串拼接
    strcat(des->note, "(");
    if(head) {  // 计算长度
        gp_node_t *pos;
        var_t *para;
    	list_for_each_entry(pos, head, entry) { 
            para = pos->addr;
            strcat(des->note, para->note);
		        if(pos->entry.next != head) // 不是最后一个参数
                    strcat(des->note, ", ");
	    }
    }
    strcat(des->note, ")");
    
}

// 增加中间变量的可读性
void gen_1_op_note(var_t *des, var_t *src, const char *format, int len_more)
{
    if(!des || !src || !src->note)
        return;
    if(des != src) {
        int len = strlen(src->note);
        free(des->note);
        des->note = calloc(1, len + len_more + 1); // + 1 是因为 \0
        if(!des->note) {
            SYSTEM_FATAL_ERR(MEM_ALLOC_FAILED);
        }
        sprintf(des->note, format, src->note);
    } else  {
        int len = strlen(src->note);
        char *tmp = calloc(1, len + len_more + 1);
        if(!tmp) {
            SYSTEM_FATAL_ERR(MEM_ALLOC_FAILED);
        }
        sprintf(tmp, format, src->note); // 先保存到临时数组中
        free(src->note); 
        des->note = tmp;
    }
}

// 增加中间变量的可读性
void gen_2_op_note(var_t *des, var_t *lval, var_t *rval, const char *format, int len_more)
{
    if(!des || !lval || !rval || !lval->note || !rval->note)
        return;
    int len = strlen(lval->note) + strlen(rval->note);

    free(des->note); // 如果 free 的参数是 ​NULL（空指针）​，则 free 函数不执行任何操作​（即安全无害）
    des->note = calloc(1, len + len_more + 1);
    if(!des->note) {
        SYSTEM_FATAL_ERR(MEM_ALLOC_FAILED);
    }
    sprintf(des->note, format, lval->note, rval->note);
}


// 添加括号
void gen_parens_note(var_t *var)
{
    if(!var || !var->note)
        return;
    int len = strlen(var->note) + 3; // ()\0
    char *tmp = calloc(1, len);
    if(!tmp) {
        SYSTEM_FATAL_ERR(MEM_ALLOC_FAILED);
    }
    sprintf(tmp, "(%s)", var->note);
    free(var->note);
    var->note = tmp;
}
/*
	取地址语句
*/
var_t *gen_lea(var_t *val)
{
    assert(val);
	if(!IS_BASE(val)) {
        sem_err(TAKE_ADDRESS_OF_ARRAY_OR_POINTER, ERROR, 
                val->note, NULL);
        return NULL;
    }
	
	if(!val->is_left){
		sem_err(EXPR_NOT_LEFT_VAL, ERROR, val->note, NULL);
		return NULL;
    }

	if(val->pointed_by){ // 被某个指针所指
		return val->pointed_by;
	} else {
		var_t *tmp = new_tmp_var(val->type, true);
        tmp->pointing_to = val; 
        gen_1_op_note(tmp, val, "&%s", 1);
		add_var(tmp); 
		// 中间代码 tmp = &val
		inter_inst_t *inst = new_general_inst(IR_OP_LEA, tmp, val, NULL);
		add_inst(inst);
		return tmp;
	}	
}


/*
	解引用语句 
    不会生成指令
    *x   x 指向谁，*x 就是谁
    var_t 如何表示 *x ?
    tmp->pointed_by = x;

    所谓解引用，就是生成表达式 *x
    这和其他一元操作 -x, ++x 并无本质的区别
    此操作也会生成中间变量，但是不会生成中间代码
    当一个变量的 pointed_by != NULL; 说明此变量就是 *x, 这是一个左值
    tmp = *x  
    *x = tmp
     需要用特殊的中间代码，而不是用普通的赋值
    所以要区分一个变量是不是 *x

*/
var_t *gen_deref(var_t *val, var_t *init)
{
	if(IS_BASE(val)){
		sem_err(DEREFERENCE_ON_BASE_TYPE, ERROR, 
                val->note, NULL); // 基本类型不能解引用
		return NULL; 
	}

	if(val->pointing_to) {
		return val->pointing_to;
	}

	var_t *tmp = new_tmp_var(val->type, false);
    tmp->init_val = init; // 针对局部数组的初始化
	tmp->is_left = true;
    
    // 让 val 指向 tmp
    // *val 就是 tmp, 可以用 tmp 表示 *val
	tmp->pointed_by = val; 
    gen_1_op_note(tmp, val, "*(%s)", 3);
	add_var(tmp);  
	return tmp;
}




var_t *gen_or(var_t *lval, var_t *rval)
{
	var_t *tmp = new_tmp_var(INT, false);
    gen_2_op_note(tmp, lval, rval, "%s || %s", 4);
	add_var(tmp);
	// 中间代码 tmp = lval || rval;
	inter_inst_t *inst = new_general_inst(IR_OP_OR, tmp, lval, rval);
	add_inst(inst);
	return tmp;
}


var_t *gen_and(var_t *lval, var_t *rval)
{
	var_t *tmp = new_tmp_var(INT, false);
    gen_2_op_note(tmp, lval, rval, "%s && %s", 4);
	add_var(tmp);
	// 中间代码 tmp = lval && rval;
	inter_inst_t *inst = new_general_inst(IR_OP_AND, tmp, lval, rval);
	add_inst(inst);
	return tmp;
}

var_t *gen_gt(var_t *lval, var_t *rval)
{
	var_t *tmp = new_tmp_var(INT, false);
    gen_2_op_note(tmp, lval, rval, "%s > %s", 3);
	add_var(tmp);
	// 中间代码 tmp = lval > rval;
	inter_inst_t *inst = new_general_inst(IR_OP_GT, tmp, lval, rval);
	add_inst(inst);
	return tmp;
}

var_t *gen_ge(var_t *lval, var_t *rval)
{
	var_t *tmp = new_tmp_var(INT, false);
    gen_2_op_note(tmp, lval, rval, "%s >= %s", 4);
	add_var(tmp);
	// 中间代码 tmp = lval >= rval;
	inter_inst_t *inst = new_general_inst(IR_OP_GE, tmp, lval, rval);
	add_inst(inst);
	return tmp;
}

var_t *gen_lt(var_t *lval, var_t *rval)
{
	var_t *tmp = new_tmp_var(INT, false);
    gen_2_op_note(tmp, lval, rval, "%s < %s", 3);
	add_var(tmp);
	// 中间代码 tmp = lval < rval;
	inter_inst_t *inst = new_general_inst(IR_OP_LT, tmp, lval, rval);
	add_inst(inst);
	return tmp;
}

var_t *gen_le(var_t *lval, var_t *rval)
{
	var_t *tmp = new_tmp_var(INT, false);
    gen_2_op_note(tmp, lval, rval, "%s <= %s", 4);
	add_var(tmp);
	// 中间代码 tmp = lval <= rval;
	inter_inst_t *inst = new_general_inst(IR_OP_LE, tmp, lval, rval);
	add_inst(inst);
	return tmp;
}


var_t *gen_equ(var_t *lval, var_t *rval)
{
	var_t *tmp = new_tmp_var(INT, false);
    gen_2_op_note(tmp, lval, rval, "%s == %s", 4);
	add_var(tmp);
	// 中间代码 tmp = (lval == rval);
	inter_inst_t *inst = new_general_inst(IR_OP_EQU, tmp, lval, rval);
	add_inst(inst);
	return tmp;
}

var_t *gen_nequ(var_t *lval, var_t *rval)
{
	var_t *tmp = new_tmp_var(INT, false);
    gen_2_op_note(tmp, lval, rval, "%s != %s", 4);
	add_var(tmp);
	// 中间代码 tmp = lval != rval;
	inter_inst_t *inst = new_general_inst(IR_OP_NEQU, tmp, lval, rval);
	add_inst(inst);
	return tmp;
}


var_t *gen_mul(var_t *lval, var_t *rval)
{
	var_t *tmp = new_tmp_var(INT, false);
    gen_2_op_note(tmp, lval, rval, "%s * %s", 3);
	add_var(tmp);
	// 中间代码 tmp = lval * rval;
	inter_inst_t *inst = new_general_inst(IR_OP_MUL, 
            tmp, lval, rval);
	add_inst(inst);
	return tmp;
}

/*
	除法语句
*/
var_t *gen_div(var_t *lval, var_t *rval)
{
	var_t *tmp = new_tmp_var(INT, false);
    gen_2_op_note(tmp, lval, rval, "%s / %s", 3);
	add_var(tmp);
	// 中间代码 tmp = lval / rval;
	inter_inst_t *inst = new_general_inst(IR_OP_DIV, tmp, lval, rval);
	add_inst(inst);
	return tmp;
}

/*
	模语句
*/
var_t *gen_mod(var_t *lval, var_t *rval)
{
	var_t *tmp = new_tmp_var(INT, false);
    gen_2_op_note(tmp, lval, rval, "%s %% %s", 3);
	add_var(tmp);
	// 中间代码 tmp = lval % rval;
	inter_inst_t *inst = new_general_inst(IR_OP_MOD, tmp, lval, rval);
	add_inst(inst);
	return tmp;
}



var_t *gen_add(var_t *lval, var_t *rval)
{
	var_t *tmp = NULL;
	if(IS_BASE(lval) && NOT_BASE(rval)){
		tmp = __copy_var_outline(rval);
		lval = gen_mul(lval, get_step(rval));	
	} else if(IS_BASE(rval) && NOT_BASE(lval)){
		tmp = __copy_var_outline(lval);
		rval = gen_mul(rval, get_step(lval));
	} else if(IS_BASE(lval) && IS_BASE(rval)){		
		tmp = new_tmp_var(INT, false);
	} else {	
        sem_err(OPERANDS_TYPE_INVALID, ERROR, 
                lval->note, rval->note);	
		return NULL;
	}
    gen_2_op_note(tmp, lval, rval, "%s + %s", 3);
	add_var(tmp);	
	inter_inst_t *inst = new_general_inst(IR_OP_ADD, 
            tmp, lval, rval);
	add_inst(inst);
	return tmp;
}


var_t *gen_sub(var_t *lval, var_t *rval)
{
	var_t *tmp = NULL;
	var_t *step = NULL;
	if(IS_BASE(lval) && NOT_BASE(rval)){ 
        sem_err(OPERANDS_TYPE_INVALID, ERROR, 
                lval->note, rval->note);	
		return NULL;
	} else if(NOT_BASE(lval) && IS_BASE(rval)){ 
		tmp = __copy_var_outline(lval);
		rval = gen_mul(rval, get_step(lval));
	} else if(IS_BASE(lval) && IS_BASE(rval)) {	
        // 都是基本类型	
		tmp = new_tmp_var(INT, false);
	} else { // 都不是基本类型	
		if(lval->type != rval->type){
			sem_err(OPERANDS_TYPE_INVALID, ERROR, 
                    lval->note, rval->note);	
		    return NULL;
		} else {  // 两个指针相减
			tmp = new_tmp_var(INT, false);
			step = get_step(lval);
		}
	}
    gen_2_op_note(tmp, lval, rval, "%s - %s", 3);
	add_var(tmp);	
	inter_inst_t *inst = new_general_inst(IR_OP_SUB, 
            tmp, lval, rval);
	add_inst(inst);

	if(step) { // 指针相减要除以步长
		return gen_div(tmp, step);
	} 
	return tmp;
}

/*   
    if(val->pointed_by)
        tmp = *(val->pointed_by); // 可以不加括号，后缀 -> 比 * 优先级高
    else
        tmp = val;
*/
var_t *gen_copy_assign(var_t *val)
{
    assert(val);
	var_t *tmp = __copy_var_outline(val);
	add_var(tmp);
   
	if(val->pointed_by){	
		// 中间代码 tmp = *(val->pointed_by)
        gen_1_op_note(tmp, val->pointed_by, "*(%s)", 3);
		inter_inst_t *inst = new_general_inst(IR_OP_LOAD, 
                tmp, val->pointed_by, NULL);
		add_inst(inst);
	} else {
		// 中间代码 tmp = val
        gen_1_op_note(tmp, val, "%s", 0);
		inter_inst_t *inst = new_general_inst(IR_OP_ASSIGN, 
                tmp, val, NULL);
		add_inst(inst);	
	}
	return tmp;
}

var_t *gen_assign(var_t *lval, var_t *rval)
{
	if(!lval->is_left){
		sem_err(LVALUE_REQUIRED, ERROR, 
                lval->note, NULL); // 需要左值
		return NULL; 
	}
	if(!var_type_compatible(lval, rval)){
        // 赋值类型不匹配
		sem_err(ASSIGN_TYPE_NOT_COMPATIBLE, ERROR, 
                lval->note, rval->note);	
		return NULL;
	}
	var_t *tmp;
	if(rval->pointed_by){ // 右值被某个指针所指
		if(!lval->pointed_by) {
	     	// 中间代码 lval = *(rval->pointed_by)
			inter_inst_t *inst = new_general_inst(IR_OP_LOAD,
                     lval, rval->pointed_by, NULL);
			add_inst(inst); 
			// 但是不能返回 lval
            // 中间代码 tmp = lval;
            tmp = gen_copy_assign(lval); // 消除左值属性
            gen_2_op_note(tmp, lval, rval->pointed_by, 
                    "%s = *(%s)", 6); // tmp 是赋值表达式的值，不是左值
			return tmp; 
		} else {  // 右值和左值都需要解引用
			// tmp = *(rval->pointed_by);
            // 不存在这样的中间指令  *a = *b  
            // 所以要转换成   tmp = *b;
            //               *a = tmp; 
			rval = gen_copy_assign(rval);	  
		}
	}
	
	if(lval->pointed_by){
		// 中间代码 *(lval->pointed_by) = tmp
		inter_inst_t *inst = new_general_inst(IR_OP_STORE, 
                rval, lval->pointed_by, NULL);
		add_inst(inst);		
		// 不能返回 lval
        tmp = gen_copy_assign(lval); 	// 消除左值属性	
        gen_2_op_note(tmp, lval->pointed_by, 
                rval, "*(%s) = %s", 6);
	} else {
		// 中间代码 lval = rval
		inter_inst_t *inst = new_general_inst(IR_OP_ASSIGN, 
                lval, rval, NULL);	
		add_inst(inst);		
        tmp = gen_copy_assign(lval);  // 消除左值属性	
        gen_2_op_note(tmp, lval, rval, "%s = %s", 3);
	}

	return tmp;
}


// int a = b;  这是初始化，不是赋值
void gen_init_inter_code(var_t *var, var_t *init)
{
	var_t *tmp;
	if(init->pointed_by){ // 被某个指针所指
		if(!var->pointed_by) {
	     	// 中间代码 var = *(init->pointed_by)
			inter_inst_t *inst = new_general_inst(IR_OP_LOAD, var, 
                    init->pointed_by, (var_t *)"init"); // Hack	 
			add_inst(inst);      
			return;
		} else {  // 都需要解引用
			 // 中间代码 init = *(init->pointed_by);
			init = gen_copy_assign(init);	  
		}
	}
	
	if(var->pointed_by){ // 对数组元素的初始化
		// 中间代码 *(var->pointed_by) = init 
		inter_inst_t *inst = new_general_inst(IR_OP_STORE, init, 
                var->pointed_by, (var_t *)"init");// Hack	 
		add_inst(inst);		
	} else {
		// 中间代码 var = init
		inter_inst_t *inst = new_general_inst(IR_OP_ASSIGN, var, 
                init, (var_t *)"init"); // Hack	 
		add_inst(inst);		
	}
}


/*
	双目运算
*/ 
var_t* gen_2_op(var_t *lval, symbol_e operator,  var_t* rval)
{
	if(!lval || !rval)
        return NULL;
	
	if(TYPE_IS_VOID(lval)){
		sem_err(OPERANDS_CANNOT_BE_VOID_TYPE, ERROR, lval->note, NULL);
		return NULL;
	}

	if(TYPE_IS_VOID(rval)){
		sem_err(OPERANDS_CANNOT_BE_VOID_TYPE, ERROR, rval->note, NULL);
		return NULL;
	}    

    if(operator == EQU || operator == NEQU || operator == LT ||
        operator == LE || operator == GT || operator == GE) {
        if(!var_type_compatible(lval, rval)) {
		    sem_err(COMPARISON_TYPE_NOT_COMPATIBLE, ERROR, 
                    lval->note, rval->note);	// 比较类型不匹配
		    return NULL;
	    }
    }

    if(operator == MUL || operator == DIV || operator == MOD) {
        if(!var_type_compatible(lval, rval)) {
		    sem_err(OPERANDS_TYPE_INVALID, ERROR, lval->note, rval->note);	
		    return NULL;
	    }
    }
	// 赋值单独处理
	if(operator == ASSIGN)
		return gen_assign(lval, rval);// 赋值
	
	// 先处理 (*p) 变量
	if(lval->pointed_by)
		lval = gen_copy_assign(lval);
	
	if(rval->pointed_by)
		rval = gen_copy_assign(rval);
	
	if(operator == OR)
		return gen_or(lval, rval); // A || B
	
	if(operator == AND)
		return gen_and(lval, rval); // A && B

	if(operator == ADD)
		return gen_add(lval, rval); // A + B
	
	if(operator == SUB)
		return gen_sub(lval, rval); // A - B	

	if(operator == EQU)
		return gen_equ(lval, rval); // A == B
	
	if(operator == NEQU)
		return gen_nequ(lval, rval); // A != B
	
	if(operator == GT)
		return gen_gt(lval, rval);
	
	if(operator == GE)
		return gen_ge(lval, rval);
	
	if(operator == LT)
		return gen_lt(lval, rval);
	
	if(operator == LE)
		return gen_le(lval, rval);
		
	if(operator == MUL)
		return gen_mul(lval, rval); // 乘
	
	if(operator == DIV)
		return gen_div(lval, rval); // 除
	
	if(operator == MOD)
		return gen_mod(lval, rval); // 取模
	
	return NULL; // 不可能到这里
}

var_t *gen_arr(var_t *array, var_t *index, var_t *init)
{
	if(!array || !index)
        return NULL;	
	if(TYPE_IS_VOID(array) ){
		sem_err(OPERANDS_CANNOT_BE_VOID_TYPE, 
                ERROR, array->note, NULL);
		return NULL;
	}
    if(TYPE_IS_VOID(index) ){
		sem_err(OPERANDS_CANNOT_BE_VOID_TYPE, 
                ERROR, index->note, NULL);
		return NULL;
	}
	if(IS_BASE(array)){
		sem_err(SUBSCRIPTED_VALUE_INVALID, 
                ERROR, array->note, NULL);
		return NULL;
	}
    if(NOT_BASE(index)) { 
        // array subscript is not an integer
		sem_err(ARRAY_SUBSCRIPT_IS_NOT_INT, 
                ERROR, index->note, NULL);
		return NULL;  
	}

	var_t *tmp = gen_add(array, index);
	return gen_deref(tmp, init);
}


void gen_para_push(var_t *arg)
{
    assert(arg);
	if(arg->pointed_by)
		arg = gen_copy_assign(arg);
	inter_inst_t *inst = new_push_arg_inst(arg);
	add_inst(inst);
}


/*
	函数调用语句 
*/
var_t *gen_call(fun_t *fun, struct list_head *head)
{
    assert(fun);
    if(fun->err_flag)
        return NULL;

    if(head)
        assert(!list_empty(head)); 
    if(head) {
        gp_node_t *pos;
	    var_t *para;
		// 逆向传递实际参数
	    list_for_each_entry_reverse(pos, head, entry) { 
            para = pos->addr;
		    gen_para_push(para);
	    }
    }

	if(TYPE_IS_VOID(fun)){
	    // 中间代码 fun();
		inter_inst_t *inst = new_fun_inst(IR_OP_PROC, fun, NULL);
		add_inst(inst);
		// todo 封装创建 void 变量的接口，这样就可以写 note,增加可读性
		return sym_tab_g.void_var; // 返回 void 特殊变量
	} else {
		var_t *ret = new_tmp_var(fun->type, fun->is_ptr);
        add_var(ret); 
		inter_inst_t *inst = new_fun_inst(IR_OP_CALL, fun, ret);
		add_inst(inst);
        gen_fun_called_note(ret, fun, head);
		return ret;
	}
}


/*
  逻辑非
*/
var_t *gen_not(var_t *val) // 外层函数已经处理了(*p)
{ 
	var_t *tmp = new_tmp_var(INT, false); // 生成整数
    gen_1_op_note(tmp, val,"!%s", 1);
	add_var(tmp);
	// 中间代码 tmp = !val;
	inter_inst_t *inst = new_general_inst(IR_OP_NOT, tmp, val, NULL);
	add_inst(inst);
	return tmp;
}



/*
	取负号
*/
var_t *gen_neg_sign(var_t *val) // 外层函数已经处理了(*p)
{
	if(NOT_BASE(val)){
		sem_err(OPERANDS_TYPE_INVALID, ERROR, val->note, NULL); 
		return NULL;
	}
	var_t *tmp = new_tmp_var(INT, false); // 生成整数
    gen_1_op_note(tmp, val,"-%s", 1);
	add_var(tmp);
	// 中间代码 tmp = -val;
	inter_inst_t *inst = new_general_inst(IR_OP_NEG, tmp, val, NULL);
	add_inst(inst);
	return tmp;
}

/*
	取正号
*/
var_t *gen_plus_sign(var_t *val) // 外层函数已经处理了(*p)
{
	if(NOT_BASE(val)){
		sem_err(OPERANDS_TYPE_INVALID, ERROR, val->note, NULL); 
		return val;
	}
	var_t *tmp = new_tmp_var(INT, false); // 生成整数，里面已经设置了不是左值
    gen_1_op_note(tmp, val,"+%s", 1);
	add_var(tmp);

	inter_inst_t *inst = new_general_inst(IR_OP_ASSIGN, tmp, val, NULL);	
	add_inst(inst);		
	return tmp;
}



// 前自增
var_t *gen_pre_inc(var_t *val)
{
	if(!val->is_left){
		sem_err(LVALUE_REQUIRED, ERROR, val->note, NULL);
		return NULL;
	}
	
	if(val->pointed_by) {  //  ++*p        
        // 中间代码 t1 = *p       
		var_t *t1 = gen_copy_assign(val);	   
        // 中间代码 t1 = t1 + 1
        inter_inst_t *inst = new_general_inst(IR_OP_ADD, 
                    t1, t1, get_step(t1));
        add_inst(inst);	
        // *p = t1
        inst = new_general_inst(IR_OP_STORE, 
                t1, val->pointed_by, NULL);
		add_inst(inst);		
        gen_1_op_note(t1, t1, "++%s", 2);
		return t1;
	} else { // ++a
		inter_inst_t *inst = new_general_inst(IR_OP_ADD,
                 val, val, get_step(val));
		add_inst(inst);
        // gen_copy_assign 的结果不是左值
		var_t *t1 = gen_copy_assign(val); 
        gen_1_op_note(t1, val, "++%s", 2); // 目的是增加中间变量的可读性
		return t1;
	}	
}


// 前自减
var_t *gen_pre_dec(var_t *val)
{
	if(!val->is_left){
		sem_err(LVALUE_REQUIRED, ERROR, val->note, NULL);
		return val;
	}
	
	if(val->pointed_by) {
        // 中间代码  t1 = *p
		var_t *t1 = gen_copy_assign(val);	    
        // 中间代码 t1 = t1 - 1
        inter_inst_t *inst = new_general_inst(IR_OP_SUB, 
                    t1, t1, get_step(t1));
        add_inst(inst);	
        // 中间代码 *p = t1
        inst = new_general_inst(IR_OP_STORE, 
                    t1, val->pointed_by, NULL);	
        add_inst(inst);		            		
		gen_1_op_note(t1, t1, "--%s", 2);
		return t1;
	} else {
        // 中间代码 val = val - 1;
		inter_inst_t *inst = new_general_inst(IR_OP_SUB, 
                val, val, get_step(val));
		add_inst(inst);
        // 中间代码 t1 = val
		var_t *t1 = gen_copy_assign(val);
		gen_1_op_note(t1, val, "--%s", 2);
		return t1;
	}	
}


// 仅支持对变量取大小,不支持操作数是类型
var_t *gen_sizeof(var_t *val)
{
	var_t *tmp = new_literal(&val->size, NUM, 0);
    gen_1_op_note(tmp, val,"sizeof %s", 7);
    add_literal(tmp);
	return tmp;
}

// 后自增
var_t *gen_post_inc(var_t *val)  
{
	if(!val->is_left){
		sem_err(LVALUE_REQUIRED, ERROR, val->note, NULL);
		return val;
	}
    // 获得 val 的副本
    // 中间代码 tmp = val; 或者 tmp = *val
	var_t *tmp = gen_copy_assign(val);	
	
	if(val->pointed_by) {  // (*val)++ 
        // 中间代码 t1 = tmp
		var_t *t1 = gen_copy_assign(tmp);	
		// 中间代码 t1 = t1 + 1
        inter_inst_t *inst = new_general_inst(IR_OP_ADD, 
                t1, t1, get_step(tmp));
		gen_1_op_note(t1, t1, "%s+1", 2);
		add_inst(inst);
		// 中间代码 *val = t1
        inst = new_general_inst(IR_OP_STORE, 
                    t1, val->pointed_by, NULL);	
        add_inst(inst);		            	            	
      
	} else { // val++
        // 中间代码 val = val + 1
		inter_inst_t *inst = new_general_inst(IR_OP_ADD, 
                val, val, get_step(val));
		add_inst(inst);
	}
	return tmp;
}

// 后自减
var_t *gen_post_dec(var_t *val)
{
	if(!val->is_left){
		sem_err(LVALUE_REQUIRED, ERROR, val->note, NULL);
		return val;
	}

	var_t *tmp = gen_copy_assign(val);	
	
	if(val->pointed_by){
		// 中间代码 t1 = tmp
		var_t *t1 = gen_copy_assign(tmp);	
        // 中间代码 t1 = t1 - 1
        inter_inst_t *inst = new_general_inst(IR_OP_SUB, t1, t1, get_step(tmp));
		gen_1_op_note(t1, t1, "%s-1", 2);
		add_inst(inst);
		// 中间代码 *val = t1
        inst = new_general_inst(IR_OP_STORE, 
                    t1, val->pointed_by, NULL);	
        add_inst(inst);		            	            	
       
	} else {
        // 中间代码 val = val - 1
		inter_inst_t *inst = new_general_inst(IR_OP_SUB, val, val, get_step(val));
		add_inst(inst);
	}	
   
	return tmp;
}


/*
	右单目运算语句
*/
var_t *gen_1_op_right(var_t *val, symbol_e operator)
{
	if(!val)
		return NULL;
	
	if(TYPE_IS_VOID(val)){
		sem_err(OPERANDS_CANNOT_BE_VOID_TYPE, ERROR, val->note, NULL);
		return NULL;
	}
	
	if(operator == INC)
		return gen_post_inc(val);
	
	if(operator == DEC)
		return gen_post_dec(val);
	
	return NULL; // 不应该到这里
}


/*
	左单目运算语句
*/
var_t *gen_1_op_left(var_t *val, symbol_e operator)
{
	if(!val)
		return NULL;
	
	if(TYPE_IS_VOID(val)){
		sem_err(OPERANDS_CANNOT_BE_VOID_TYPE, ERROR, val->note, NULL);
		return NULL;
	}

	if(operator == LEA)
		return gen_lea(val); // 取地址语句
	
	if(operator == MUL)
		return gen_deref(val, NULL); // 解引用

	if(operator == INC)
		return gen_pre_inc(val); // 前自增
	
	if(operator == DEC)
		return gen_pre_dec(val); // 前自减
	
	if(operator == SIZEOF)
		return gen_sizeof(val);		
	
	if(val->pointed_by)
		val = gen_copy_assign(val); // 处理(*p) 为后面的服务
	
	if(operator == NOT)
		return gen_not(val); // 逻辑非
	
	if(operator == SUB)
		return gen_neg_sign(val);// 取负语句

	if(operator == ADD)
		return gen_plus_sign(val); //取正语句
		
	return NULL; // 不应该到这里
}




/*
	产生变量初始化语句
*/
void gen_var_init(var_t *var)
{
	assert(var);
	if(var->is_literal)
		return;

     // 添加变量声明指令(仅限局部变量)
	add_inst(new_general_inst(IR_OP_DECL, NULL, var, NULL));

    var_t *init_val = var->init_val;
    if(!init_val) {
        return;  // 没有初始化式
    }
    
    if(init_val->is_literal) {
        var->init_by_constant = true;  
        if(init_val->is_arr && IS_CHAR_PTR(var)) { // char *p = "hello";
            var->string_val = init_val->name; // 字符串的名字
        } else {
            var->int_val = init_val->int_val; // 拷贝初始化值
        }
    } else { // 初始化值不是字面量
        if(IS_GLOBAL(var) && init_val->pointing_to) { // int *p = &a;           
            var->init_by_constant = true; 
        } else {
			// 只有这一种情况,生成赋值语句 
            gen_init_inter_code(var, var->init_val);          
        }
    }
}

void __gen_arr_init_by_list(var_t *arr)
{
    gp_node_t *node;
	int i = 0;
	list_for_each_entry(node, &arr->arr_init_val, entry) {
		var_t *init_val = node->addr;
		var_t *index = new_literal(&i, NUM, 0);
        add_literal(index);
		var_t *ele = gen_arr(arr, index, init_val);
		i++;
	}
   
    while(i < arr->ele_num) {
        var_t *index = new_literal(&i, NUM, 0);
        add_literal(index);
        var_t *ele = gen_arr(arr, index, sym_tab_g.zero);
        i++;
    }
}


void __gen_arr_init_by_string(var_t *arr)
{
    int i = 0;
    char *p = arr->init_val->string_val;
    while(*p) {
        var_t *index = new_literal(&i, NUM, 0);
        add_literal(index);
        var_t *one_char = new_literal(p, CHARA, arr->line_num);
        add_literal(one_char);
		var_t *ele = gen_arr(arr, index, one_char);
		i++;
        p++;
    }

    while(i < arr->ele_num) {
        var_t *index = new_literal(&i, NUM, 0);
        add_literal(index);
        var_t *ele = gen_arr(arr, index, sym_tab_g.zero);
        i++;       
    }
}

void gen_arr_init(var_t *arr)
{
	assert(arr);
	if(arr->is_literal)
		return;
	// 添加变量声明指令(仅限局部变量)
	
	add_inst(new_general_inst(IR_OP_DECL, NULL, arr, NULL));
    if(!array_is_initialized(arr)) // 不包含初始化
        return;
    if(IS_GLOBAL(arr)) {
        arr->init_by_constant = true; // 只能用常量初始化，不然会报错
        return;
    } 
	
    if(arr->init_val) {
        __gen_arr_init_by_string(arr);
    } else {
 		__gen_arr_init_by_list(arr);
	}
}


void set_fun_return_point(fun_t *fun, inter_inst_t *inst)
{
	assert(fun && inst);
	fun->ret_point = inst;
}

/*
	生成函数入口语句
*/
void gen_fun_entry(fun_t *fun)
{
	if(!fun)
		return;
	// 添加函数入口指令
	add_inst(new_fun_inst(IR_OP_FUN_ENTRY, fun, NULL));
	// 创建函数返回点
	set_fun_return_point(fun, new_label_inst("return"));  
}


/*
	生成函数出口语句
*/
void gen_fun_exit(fun_t *fun)
{
	if(!fun)
		return;
	// 添加函数返回点，return 语句的 Label
	add_inst(fun->ret_point);
	// 添加函数出口指令
	add_inst(new_fun_inst(IR_OP_FUN_EXIT, fun, NULL)); 
}


/*
C语言标准规定，如果一个非 void 类型的函数执行结束但未遇到 return 语句，
则程序的行为是未定义的 
*/

void gen_return(var_t *ret_val)
{
	if(!ret_val)
		return; // 如果语法或语义有错，ret_val 为 NULL

	fun_t *fun = sym_tab_g.cur_fun;
	assert(fun);

	if(!fun_return_type_check_ok(fun, ret_val)) {
		sem_err(INCOMPATIBLE_RETURN_TYPE, ERROR, ret_val->note, NULL);
		return;
	}

	inter_inst_t *ret_point = fun->ret_point; // 获取返回点
	
	if(TYPE_IS_VOID(ret_val)) {
		add_inst(new_jmp_inst(IR_OP_RET, ret_point, NULL, NULL));
	} else {
		if(ret_val->pointed_by) {
			ret_val = gen_copy_assign(ret_val);	  
		}
		add_inst(new_jmp_inst(IR_OP_RET_VAL, ret_point, ret_val, NULL));
	}
}



/*
	产生 if 头部
	注意：没有 if 尾部
*/

void gen_if_head(var_t *cond, inter_inst_t **lb_else)
{
	assert(lb_else);

	*lb_else = new_label_inst("else"); // 产生 else 标签
	if(cond) {
		if(cond->pointed_by)
			cond = gen_copy_assign(cond); // 处理 *p

		add_inst(new_jmp_inst(IR_OP_JF, *lb_else, cond, NULL));
	}	
}


/*
	产生 else 头部
*/
void gen_else_head(inter_inst_t *lb_else, inter_inst_t **lb_exit)
{
	assert(lb_exit);
	*lb_exit = new_label_inst("exit"); // 产生 exit 标签
	add_inst(new_jmp_inst(IR_OP_JMP, *lb_exit, NULL, NULL));
	add_inst(lb_else);	
}

/*
	产生 else 尾部
*/
void gen_else_tail(inter_inst_t *lb_exit)
{	
	add_inst(lb_exit);	
}

/*
	产生 while 循环头部
@L1_while:

*/

void gen_while_head(inter_inst_t **lb_while, 
					inter_inst_t **lb_exit)
{
	assert(lb_while && lb_exit);
	*lb_while = new_label_inst("while");
	add_inst(*lb_while);
	*lb_exit = new_label_inst("exit");
	push_labels(*lb_while, *lb_exit);
}

/*
	IR_OP_JF (cond) @exit
*/
void gen_while_cond(var_t *cond, inter_inst_t *lb_exit)
{
	if(cond){
		if(TYPE_IS_VOID(cond)){
			// void 函数返回值不能出现在表达式中
			sem_err(EXPR_IS_VOID, ERROR, NULL, NULL); 
			return;
		} else if(cond->pointed_by){
			 // while(*p), while(a[0])
			cond = gen_copy_assign(cond);
		}
		
		add_inst(new_jmp_inst(IR_OP_JF, lb_exit, cond, NULL));
	}
}

/*
	产生 while 尾部
	IR_OP_JMP @while
@exit:
*/
void gen_while_tail(inter_inst_t *lb_while, 
	                inter_inst_t *lb_exit)
{
	add_inst(new_jmp_inst(IR_OP_JMP, lb_while, NULL, NULL));
	add_inst(lb_exit);
	pop_labels(); // 离开 while
}


/*
	产生 do-while 循环头部
	@do:
*/
void gen_do_while_head(inter_inst_t **lb_do, 
	                   inter_inst_t **lb_exit)
{
	assert(lb_do && lb_exit);
	*lb_do = new_label_inst("do");
	add_inst(*lb_do);
	*lb_exit = new_label_inst("exit");
	push_labels(*lb_do, *lb_exit); 
}


/*
	产生 do-while 尾部
	IR_OP_JT (cond) @do
@exit:
*/
void gen_do_while_tail(var_t *cond, inter_inst_t *lb_do, 
	                              inter_inst_t *lb_exit)
{
	
	if(cond){
		if(TYPE_IS_VOID(cond)){
			// void 函数返回值不能出现在表达式中
			sem_err(EXPR_IS_VOID, ERROR, NULL, NULL); 
			return;
		} else if(cond->pointed_by){
			cond = gen_copy_assign(cond); 
		}
		add_inst(new_jmp_inst(IR_OP_JT, lb_do, cond, NULL));
	}
	add_inst(lb_exit);
	pop_labels(); 
}

/*
@for:

*/
void gen_for_head(inter_inst_t **lb_for, inter_inst_t **lb_exit, 
				  inter_inst_t **lb_iter)
{
	assert(lb_for && lb_exit && lb_iter);
	*lb_for = new_label_inst("for");
	*lb_exit = new_label_inst("exit");
	*lb_iter = new_label_inst("iter");
	add_inst(*lb_for);
	push_labels(*lb_iter, *lb_exit); // 为 break, continue 服务
}

/*
// 求 cond 
IR_OP_JF (cond) @exit

*/
void gen_for_body(var_t *cond, inter_inst_t *lb_exit)
{
	if(cond){
		if(TYPE_IS_VOID(cond)){
			cond = sym_tab_g.one;			
		} else if(cond->pointed_by){
			cond = gen_copy_assign(cond); 
		}
		add_inst(new_jmp_inst(IR_OP_JF, lb_exit, cond, NULL));
	}
	
}


/*
@iter:
// 迭代表达式
*/
void gen_for_iter(inter_inst_t *lb_iter)
{
	add_inst(lb_iter);
}

/*
	IR_OP_JMP @for
@exit:
*/
void gen_for_tail(inter_inst_t *lb_exit, inter_inst_t *lb_for)
{
	add_inst(new_jmp_inst(IR_OP_JMP, lb_for, NULL, NULL)); 
	add_inst(lb_exit); 
	pop_labels(); 
}



/*
	产生 switch 头部
*/

void gen_switch_head(inter_inst_t **lb_exit)
{
	assert(lb_exit);
	// 产生 exit 标签，因为 push_labels 要用
	*lb_exit = new_label_inst("exit");  
	// 进入 switch，不允许 continue，因此 begin = NULL
	push_labels(NULL, *lb_exit);  
}

/*
	产生 switch 尾部
@exit:
*/
void gen_switch_tail(inter_inst_t *lb_exit)
{
	add_inst(lb_exit);	
	pop_labels();
}



void gen_case_select(struct list_head *head, var_t *cond, inter_inst_t *exit)
{
	assert(head);
	case_info_t *node;
	inter_inst_t *dft_lb = NULL;
    list_for_each_entry(node, head, entry) {
        var_t *lb = node->case_val;
        if(lb->is_arr) {  // 说明是 default
            dft_lb = node->case_entry;
			continue;
        } 
		add_inst(new_jmp_inst(IR_OP_JE, node->case_entry, cond, lb));
    }	
	if(dft_lb) {
		add_inst(new_jmp_inst(IR_OP_JMP, dft_lb, NULL, NULL));
	} else {
		add_inst(new_jmp_inst(IR_OP_JMP, exit, NULL, NULL));
	}
}

bool gen_case_entry(struct list_head *head, var_t *val)
{
    assert(head);
    case_info_t *node;
    var_t *find = NULL;

	// 判断 case 标签是否重复
    list_for_each_entry(node, head, entry) {
        var_t *lb = node->case_val;
        if(lb->is_arr && val->is_arr) {  
			// hack 因为是字符数组
            sem_err(MULTIPLE_DEFAULT_LABELS, 
					ERROR, NULL, (void *)&lb->line_num);
            return false;
        } else if(val->int_val == lb->int_val) {
            sem_err(DUPLICATE_CASE_VALUE, ERROR,
					 lb->note, (void *)&lb->line_num);
            return false;
        }
    }

	case_info_t *case_info = calloc(1, sizeof(inter_inst_t));						 
	if(!case_info){
        list_destroy(head, case_info_t, entry);
		SYSTEM_FATAL_ERR(MEM_ALLOC_FAILED);
	}
    case_info->case_val = val;
    char tmp[10] = {0};
    if(!val->is_arr)
        snprintf(tmp, sizeof(tmp), "case_%d", val->int_val);
    else 
        snprintf(tmp, sizeof(tmp), "default");
	// 插入标号 case_x 或 default
    case_info->case_entry = new_label_inst(tmp);  
    add_inst(case_info->case_entry);
	// 新的标签，加入链表
    list_add_tail(&case_info->entry, head); 
 
    return true;
}


/*
	产生 break 语句
*/
void gen_break(void)
{
	inter_inst_t *lb = get_top_label(&lb_stack_g.end);

	if(lb)
		add_inst(new_jmp_inst(IR_OP_JMP, lb, NULL, NULL));
	else 
		sem_err(BREAK_NOT_WITHIN_LOOP_OR_SWITCH, ERROR, NULL, NULL); 
}

/*
	产生 continue 语句
*/
void gen_continue(void)
{
	inter_inst_t *lb = get_top_label(&lb_stack_g.begin);
	
	if(lb)
		add_inst(new_jmp_inst(IR_OP_JMP, lb, NULL, NULL));
	else 
		sem_err(CONTINUE_NOT_WITHIN_LOOP, ERROR, NULL, NULL); 
}



// 把 begin 后面的节点移动到新的链表，（不包括 begin）
void move_list_to_new_head(struct list_head *begin, struct list_head *new_head)
{
    assert(new_head && begin);
    while(begin->next != &sym_tab_g.cur_fun->inter_code)
        list_move_tail(begin->next, new_head);

}

// 把临时链表的节点移动到 sym_tab_g.cur_fun->inter_code 的尾部
void put_list_back(struct list_head *head)
{ 
    assert(head);
    while(!list_empty(head)) {
        list_move_tail(head->next, &sym_tab_g.cur_fun->inter_code);
    }
}
